package jMiiEditor.gui.swingintrospection;

import javax.swing.ComboBoxModel;
import jMiiEditor.mii.MIIGETTER;
import jMiiEditor.mii.Mii;
import jMiiEditor.mii.introspection.MiiGetterIntrospectionItem;
import org.apache.log4j.Logger;
import cx.ath.choisnet.lang.introspection.IntrospectionInvokeException;
import cx.ath.choisnet.lang.introspection.method.IntrospectionItem;
import cx.ath.choisnet.swing.introspection.FrameFieldPopulator;
import cx.ath.choisnet.swing.introspection.SwingIntrospectorIllegalAccessException;
import cx.ath.choisnet.swing.introspection.SwingIntrospectorIllegalArgumentException;
import cx.ath.choisnet.swing.introspection.SwingIntrospectorItem;
import cx.ath.choisnet.swing.introspection.SwingIntrospectorRootItem;
import utils.BinStuffs;

public class MiiFrameFieldPopulator<FRAME>
    implements FrameFieldPopulator<FRAME,Mii>
{
    /** Some logs */
    private static Logger slogger = Logger.getLogger(MiiFrameFieldPopulator.class);

    private FRAME   frame;
    private Mii     readingMiiObject;

    public MiiFrameFieldPopulator(
            FRAME   populateObject,
            Mii     readingMiiObject
            )
    {
        this.readingMiiObject   = readingMiiObject;
        this.frame              = populateObject;
    }

    /**
     * Put computed value on all Item with an index != 0, put !value on all Item with an index == 0
     * @param fdList list of SwingIntrospectorItem
     * @param item current MiiGetterInspectionOLD.Item when value will be read
     * @see #Item.getBeanNameIndex()
     * @throws IntrospectionInvokeException
     * @throws SwingIntrospectorIllegalAccessException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    private void populateBOOL(
            final Iterable<SwingIntrospectorItem<FRAME>>    swItemIterable,
            final MiiGetterIntrospectionItem                item
            )
        throws IntrospectionInvokeException, SwingIntrospectorIllegalAccessException
    {
        /*
            java.lang.Object
              extended by java.awt.Component
                  extended by java.awt.Container
                      extended by javax.swing.JComponent
                          extended by javax.swing.AbstractButton
                              extended by javax.swing.JToggleButton
                                  extended by javax.swing.JCheckBox
        */
        boolean value = item.getBooleanValue( this.readingMiiObject );

        for( SwingIntrospectorItem<FRAME> switem : swItemIterable ) {
            Object obj = switem.getFieldObject( frame );

            if( obj instanceof javax.swing.JToggleButton ) {
                javax.swing.JToggleButton jtf = javax.swing.JToggleButton.class.cast( obj );
                jtf.setSelected( (switem.getIndex() != 0) ? value : !value );
                }
        }
    }

    private void populateBYTES4( final Iterable<SwingIntrospectorItem<FRAME>> swItemIterable, final MiiGetterIntrospectionItem item )
        throws IntrospectionInvokeException, SwingIntrospectorIllegalAccessException
    {
        byte[] value = item.getBytesValue( this.readingMiiObject );

        for( SwingIntrospectorItem<FRAME> switem : swItemIterable ) {
            Object obj = switem.getFieldObject( frame );

            if( obj instanceof javax.swing.text.JTextComponent ) {
                javax.swing.text.JTextComponent jtf = javax.swing.JTextField.class.cast( obj );
                jtf.setText( BinStuffs.ubyteToHexString( value[ switem.getIndex()] ) );
                }
        }
    }

    private void populateINT( final Iterable<SwingIntrospectorItem<FRAME>> swItemIterable, final MiiGetterIntrospectionItem item )
        throws IntrospectionInvokeException,
               SwingIntrospectorIllegalAccessException,
               SwingIntrospectorIllegalArgumentException
    {
        /*
            java.lang.Object
              extended by java.awt.Component
                  extended by java.awt.Container
                      extended by javax.swing.JComponent
                          extended by javax.swing.JScrollBar
            java.lang.Object
              extended by java.awt.Component
                  extended by java.awt.Container
                      extended by javax.swing.JComponent
                          extended by javax.swing.JComboBox
         */
        int value = item.getIntegerValue( this.readingMiiObject );

        for( SwingIntrospectorItem<FRAME> switem : swItemIterable ) {
            //f.setAccessible(true);
            Object obj = switem.getFieldObject( frame );

            //slogger.info( "field " + obj );

            if( obj instanceof javax.swing.text.JTextComponent ) {
                javax.swing.text.JTextComponent jtf = javax.swing.JTextField.class.cast( obj );
                jtf.setText( Integer.toString( value ) );
                }
            else if( obj instanceof javax.swing.JScrollBar) {
                javax.swing.JScrollBar jsb = javax.swing.JScrollBar.class.cast( obj );
                jsb.setValue( value );
            }
            else if( obj instanceof javax.swing.JComboBox ) {
                javax.swing.JComboBox<?> jcb = javax.swing.JComboBox.class.cast( obj );

                try {
                    jcb.setSelectedIndex( value );
                }
                catch( IllegalArgumentException e ) {
                    ComboBoxModel<?> model = jcb.getModel();
                    slogger.warn( "value=" + value + " model[" + model.getSize() + "]" + model, e );
                    //TODO:
                    //throw new SwingIntrospectorIllegalArgumentException( item.getGetterMethod(), value, e );
                }
            }
            else if( obj instanceof javax.swing.JSpinner ) {
                javax.swing.JSpinner jsp = javax.swing.JSpinner.class.cast( obj );

                // TODO: make some extras checks here !
                jsp.setValue( new Integer( value ) ); // Should have a model which work with integer
            }
            else if( obj instanceof javax.swing.JSlider ) {
                javax.swing.JSlider js = javax.swing.JSlider.class.cast( obj );

                js.setValue( value );
            }
        }
    }

    private void populateRAWSTRING(
            final Iterable<SwingIntrospectorItem<FRAME>> swItemIterable,
            final MiiGetterIntrospectionItem item
            )
        throws  IntrospectionInvokeException,
                SwingIntrospectorIllegalAccessException
    {
        /*
            java.lang.Object
              extended by java.awt.Component
                  extended by java.awt.Container
                      extended by javax.swing.JComponent
                          extended by javax.swing.text.JTextComponent
                              extended by javax.swing.JTextField
         */
        String value = item.getStringValue( this.readingMiiObject );

        for( SwingIntrospectorItem<FRAME> switem : swItemIterable ) {
            //f.setAccessible(true);
            Object obj = switem.getFieldObject( frame );

            //slogger.info( "field " + obj );

            if( obj instanceof javax.swing.text.JTextComponent ) {
                javax.swing.text.JTextComponent jtf = javax.swing.JTextField.class.cast( obj );
                jtf.setText( value );
                }
        }
    }

//    public void populate( final SwingIntrospectorRootItem<FRAME> rootItem, final MiiGetterIntrospectionItem item )
//        throws SwingIntrospectorIllegalAccessException,
//               SwingIntrospectorIllegalArgumentException,
//               IntrospectionInvokeException
//    {
//        populateIterable( rootItem, item );
//    }


    private void miiPopulateIterable(
            final Iterable<SwingIntrospectorItem<FRAME>>    swItemIterable,
            final MiiGetterIntrospectionItem                item
            )
        throws IntrospectionInvokeException,
               SwingIntrospectorIllegalAccessException,
               SwingIntrospectorIllegalArgumentException
    {
//        if( slogger.isDebugEnabled() ) {
//            slogger.debug( "populateIterable() : " + item );
//            for( SwingIntrospectorItem switem : swItemIterable ) {
//                slogger.debug( "Set Field : " + switem.getField().getName() );
//            }
//        }
        MIIGETTER.Type type = item.getType();

        if( type == MIIGETTER.Type.BOOL ) {
            populateBOOL( swItemIterable, item );
        }
        else if( type == MIIGETTER.Type.BYTES4 ) {
            populateBYTES4( swItemIterable, item );
        }
        else if( type == MIIGETTER.Type.INT ) {
            populateINT( swItemIterable, item );
        }
        else if( type == MIIGETTER.Type.RAWSTRING ) {
            populateRAWSTRING( swItemIterable, item );
        }
        else {
            throw new RuntimeException( "MIIGETTER.Type unkwow: " + type );
        }
    }

    @Override
    public void populateFields(
            SwingIntrospectorRootItem<FRAME>    rootItem,
            IntrospectionItem<Mii>              iItem
            )
    throws  SwingIntrospectorIllegalAccessException,
            SwingIntrospectorIllegalArgumentException,
            IntrospectionInvokeException
    {
        MiiGetterIntrospectionItem miiIItem = MiiGetterIntrospectionItem.class.cast( iItem );

        miiPopulateIterable(rootItem, miiIItem);
    }
}
